/*
 * Copyright (c) 2017-2019, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2019/08/08
 *
 * History:
 *
 */

#ifndef __LINDENI_PLYAER__
#define __LINDENI_PLYAER__

#ifdef __cplusplus
extern "C" {
#endif

#include "osal_types.h"
#include "lindcomponent.h"

typedef long player_handle_t;

#define SEEK_BACKWARD       0
#define SEEK_FORWARD        1

typedef enum _MessageType_e
{
    LINDPLAYER_MSG_UNKNOWN              = 0,

    //
    LINDPLAYER_MSG_EOF,
    LINDPLAYER_MSG_FORCE_EXIT,
    LINDPLAYER_MSG_BUFFERING_START,
    LINDPLAYER_MSG_BUFFERING_END,
} MessageType_e;

typedef enum _PlayerStatus_e
{
    LINDPLAYER_STATUS_ERROR             = 0x80000000,
    LINDPLAYER_STATUS_IDLE              = 0,

    // player status
    LINDPLAYER_STATUS_PREPARE           = 0x1,
    LINDPLAYER_STATUS_PAUSE             = 0x2,
    LINDPLAYER_STATUS_START             = 0x4,
    LINDPLAYER_STATUS_STOP              = 0x8,
    LINDPLAYER_STATUS_BUFFERING         = 0x10,

    // seek status
    LINDPLAYER_STATUS_SEEK_NONE         = 0x1000,
    LINDPLAYER_STATUS_SEEK_VIDEO        = 0x2000,
    LINDPLAYER_STATUS_SEEK_AUDIO        = 0x4000,
    LINDPLAYER_STATUS_SEEK_START        = LINDPLAYER_STATUS_SEEK_VIDEO | LINDPLAYER_STATUS_SEEK_AUDIO,
    LINDPLAYER_STATUS_SEEK_END          = 0x8000,
} PlayerStatus_e;

typedef int (* lindplayer_cb)(void * user, MessageType_e msg, int ext1, int ext2);

/**
 * cb: callback function called by player framework.
 * user: who will response the callback funtion.
 * is_live: indicate this is an real time video.
 * transport: use for rtsp player setting mpegts transport type('udp' or 'tcp')
 */
typedef struct _lindplayer_config_t
{
    lindplayer_cb   cb;
    void *          user;

    int             is_live;

    /*
     * For live stream, 'tcp' or 'udp', default 'udp' if not set.
     */
    char            transport[8];

    /*
     * display postion: [x, y, w, h].
     */
    rect_t          disp_pos;

    int             disable_audio;
    int             disable_video;

    /*
     * display rotate degree.
     */
    rotate_degree_e disp_rotate;

    /*
     * the layer z-order
     *  range [0, 16]: from bottom to up
     */
    int             z_order;

    /*
     * channel id: 0 or 1
     *  0. Display engine has 2 video channels.
     *  1. Each video channel has 4 layers.
     *  2. All layers in the same channel must be the same attribution('format', 'size', 'scale ratio')
     *  3. Layers in different channel can be different attribution.
     *  4. Upto 4 different layers with the same resolution can be in the same channel.
     *  5. Layers with the different resolution must be in the different channel.
     */
    int             channel_id;
} lindplayer_config_t;

/**
 * usally a player will be called like this:
 *    step 1: call player_create()
 *        to create a player.
 *    step 2: call player_set_parameters()
 *        set callback function to monitor some message from the palyer framework.
 *        set some other parameters to the player which can be used for playing.
 *    step 3: call player_set_data_source()
 *        to tell the player where is the video file or stream to play.
 *    step 4: call player_prepare()
 *        to let the player ready to play.
 *    step 5: call player_start()
 *        now start to play.
 *    step 6: call player_pause() / player_seek() / player_stop()
 *        to change the player status.
 *    step 7: call player_destroy()
 *        before exit the player.
 */

/**
 * create a player object.
 * @param
 * @return
 *    NULL: create player failed.
 *    others: a player handle.
 */
player_handle_t player_create();

/**
 * call player_destroy to destroy the player before exit the app.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 */
void player_destroy(player_handle_t player_handle);

/**
 * !!!Deprecated. It was replaced by player_set_parameters.
 * app set a callback funtion to monitor some message such as eof.
 *
 * @param
 *    player_handle[in]: player handle
 *    p_config[in]: parameters.
 * @return
 */
void player_set_callback(player_handle_t player_handle, lindplayer_cb cb, void * user);

/**
 * app set some parameters to the player which can be used for playing.
 *
 * @param
 *    player_handle[in]: player handle
 *    p_config[in]: parameters.
 * @return
 */
void player_set_parameters(player_handle_t player_handle, lindplayer_config_t * p_config);

/**
 * tell the player to play the file or stream located by url.
 *
 * @param
 *    player_handle[in]: player handle
 *    url[in]: play the file or stream located here.
 *         it can be a local file, such as /sdcard/1.ts,
 *         also can be a stream from network, such as http://xxx/1.ts.
 * @return
 *    0 success, -1 error
 */
int player_set_data_source(player_handle_t player_handle, const char * url);

/**
 * let the player prepare to play.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    0 success, -1 error
 */
int player_prepare(player_handle_t player_handle);

/**
 * let player start to play.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    0 success, -1 error
 */
int player_start(player_handle_t player_handle);

/**
 * let player stop playing.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    0 success, -1 error
 */
int player_stop(player_handle_t player_handle);

/**
 * let player pause or continue to play alternately.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    0 success, -1 error
 */
int player_pause(player_handle_t player_handle);

/**
 * let player pause or continue to play alternately.
 *
 * @param
 *    player_handle[in]: player handle
 *    flag[in]: 1 pause, 0 resume
 * @return
 *    0 success, -1 error
 */
int player_pause2(player_handle_t player_handle, int flag);

/**
 * seek to a relative position of timestamp.
 *
 * @param
 *    player_handle[in]: player handle
 *    seek_direction[in]: if set to SEEK_BACKWARD, player will seek backward;
 *                    if set to SEEK_FORWARD, player will seek forward.
 *                    how long to seek will be defined by next parameter step_us.
 *    step_us[in]: will seek forward or backward step_us relative to current postition.
 * @return
 *    0 success, -1 error
 */
int player_seek(player_handle_t player_handle, int seek_direction, int64_t step_us);

/**
 * seek to an absolute position of timestamp.
 *
 * @param
 *    player_handle[in]: player handle
 *    pos_us[in]: will seek here to play, unit: us.
 * @return
 *    0 success, -1 error
 */
int player_seekto(player_handle_t player_handle, int64_t pos_us);

/**
 * get video duration.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    the total video duration, unit: us.
 */
int64_t player_get_duration(player_handle_t player_handle);

/**
 * get current playing position.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    current playing position, unit: us.
 */
int64_t player_get_cur_pos(player_handle_t player_handle);

/**
 * get current playing status.
 *
 * @param
 *    player_handle[in]: player handle
 * @return
 *    current playing status.
 */
PlayerStatus_e player_get_cur_status(player_handle_t player_handle);

/**
 * set playback speed.
 *
 * @param
 *    player_handle[in]: player handle
 *    speed_num[in]:
 *    speed_den[in]:
 *      speed_x = speed_num / speed_den
 *      in range: 1/16x, 1/8x, ... , 8x, 16x
 * @return
 *    0 success, -1 error
 */
int player_set_speed(player_handle_t player_handle, unsigned int speed_num, unsigned int speed_den);

/**
 * hide or show the UI layer.
 *
 * @param
 *    player_handle[in]: player handle
 *    show[in]:
 *      0: hide ui
 *      1: show ui
 * @return
 *    0 success, -1 error
 */
int player_show_ui(player_handle_t player_handle, int show);

/**
 * get current version.
 *
 * @param
 * @return
 *    current version.
 */
char * get_player_version();

#ifdef __cplusplus
}
#endif

#endif	// __LINDENI_PLYAER__

